import tkinter as tk
from tkinter import messagebox, simpledialog
import json
import os



class Node:
    """自定义链表节点"""
    def __init__(self, student):
        self.student = student
        self.next = None


class LinkedList:
    """自定义链表"""
    def __init__(self):
        self.head = None

    def append(self, student):
        """在链表末尾添加学生"""
        new_node = Node(student)
        if not self.head:
            self.head = new_node
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_node

    def to_list(self):
        """将链表转换为列表（仅用于显示）"""
        result = []
        current = self.head
        while current:
            result.append(current.student)
            current = current.next
        return result


class Student:
    def __init__(self, name, scores=None):
        self.name = name
        self.scores = scores if isinstance(scores, dict) else {}
        self.total_score = sum(self.scores.values()) if self.scores else 0

    def update_total_score(self):
        """更新学生的总分"""
        self.total_score = sum(self.scores.values())

    def __repr__(self):
        return f"Student(name={self.name}, total_score={self.total_score})"


class Class:
    def __init__(self):
        self.students = LinkedList()  # 使用自定义链表存储学生

    def add_student(self, student):
        """添加学生到班级"""
        self.students.append(student)

    def sort_students_by_name(self):
        """按姓名排序学生（冒泡排序）"""
        head = self.students.head
        if not head or not head.next:
            return

        swapped = True
        while swapped:
            swapped = False
            current = head
            while current.next:
                if current.student.name.lower() > current.next.student.name.lower():
                    # 交换两个节点的数据
                    current.student, current.next.student = current.next.student, current.student
                    swapped = True
                current = current.next

    def sort_students_by_total_score(self):
        """按总分从高到低排序学生（选择排序）"""
        head = self.students.head
        if not head or not head.next:
            return

        current = head
        while current:
            max_node = current
            runner = current.next
            while runner:
                if runner.student.total_score > max_node.student.total_score:
                    max_node = runner
                runner = runner.next
            # 交换当前节点与最大值节点的数据
            if max_node != current:
                current.student, max_node.student = max_node.student, current.student
            current = current.next

    def sort_students_by_course_score(self, course_name):
        """按特定课程的成绩从高到低排序学生（选择排序）"""
        head = self.students.head
        if not head or not head.next:
            return

        current = head
        while current:
            max_node = current
            runner = current.next
            while runner:
                score_current = current.student.scores.get(course_name, 0)
                score_runner = runner.student.scores.get(course_name, 0)
                if score_runner > score_current:
                    max_node = runner
                runner = runner.next
            # 交换当前节点与最大值节点的数据
            if max_node != current:
                current.student, max_node.student = max_node.student, current.student
            current = current.next

    def find_student_by_name(self, name):
        """根据姓名查找学生（线性搜索）"""
        clean_name = self._clean_name(name)
        current = self.students.head
        while current:
            if self._clean_name(current.student.name) == clean_name:
                return current.student
            current = current.next
        return None

    @staticmethod
    def _clean_name(name):
        """清理姓名：去除空格、下划线，转为小写"""
        return name.strip().replace(" ", "").replace("_", "").lower()

    def __repr__(self):
        return f"Class(students={self.students.to_list()})"


class CourseManagement:
    def __init__(self, root):
        self.root = root
        self.root.title("Course Management System")

        self.class_obj = Class()  # 初始化班级

        self.create_initial_widgets()

        self.output_label = tk.Label(self.root, text="Output")
        self.output_label.pack()
        self.output_text = tk.Text(self.root, height=15, width=70)
        self.output_text.pack()

        self.load_and_integrate_data()

    def create_initial_widgets(self):
        self.show_management_button = tk.Button(self.root, text="Course Management", command=self.show_management_widgets)
        self.show_management_button.pack()

    def show_management_widgets(self):
        self.show_management_button.pack_forget()

        self.sort_by_name_button = tk.Button(self.root, text="Sort Students by Name", command=self.sort_students_by_name)
        self.sort_by_name_button.pack()

        self.sort_by_total_score_button = tk.Button(self.root, text="Sort Students by Total Score", command=self.sort_students_by_total_score)
        self.sort_by_total_score_button.pack()

        self.sort_by_course_score_button = tk.Button(self.root, text="Sort Students by Course Score", command=self.sort_students_by_course_score)
        self.sort_by_course_score_button.pack()

        self.display_class_button = tk.Button(self.root, text="Display Class", command=self.display_class)
        self.display_class_button.pack()

    def load_and_integrate_data(self):
        """加载 students.json 和 grades.json 并整合数据"""
        resources_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ressources')
        students_file_path = os.path.join(resources_dir, 'students.json')
        grades_file_path = os.path.join(resources_dir, 'grades.json')

        try:
            # 加载 students.json
            with open(students_file_path, 'r', encoding='utf-8') as file:
                students_data = json.load(file)
                for student_data in students_data['students']:
                    student_name = student_data['fullName']
                    student = Student(student_name)
                    self.class_obj.add_student(student)
                    self.output_text.insert(tk.END, f"Loaded student: {student_name}\n")
        except FileNotFoundError:
            self.output_text.insert(tk.END, "students.json file not found.\n")
            return
        except json.JSONDecodeError:
            self.output_text.insert(tk.END, "Error decoding JSON from students.json file.\n")
            return

        try:
            # 加载 grades.json
            with open(grades_file_path, 'r', encoding='utf-8') as file:
                grades_data = json.load(file)
                unmatched_students = []  # 记录未匹配的学生
                for course_name, course_data in grades_data['grades_per_course'].items():
                    for student_name, scores in course_data.items():
                        # 使用清理后的姓名进行匹配
                        clean_student_name = Class._clean_name(student_name)
                        student = self.class_obj.find_student_by_name(clean_student_name)
                        if student:
                            # 计算平均分作为该课程的成绩
                            average_score = sum(scores) / len(scores)
                            student.scores[course_name] = average_score
                            student.update_total_score()
                            self.output_text.insert(
                                tk.END,
                                f"Updated {student.name}'s score for {course_name}: {average_score:.2f}\n"
                            )
                        else:
                            unmatched_students.append(student_name)
                
                if unmatched_students:
                    self.output_text.insert(tk.END, "\nUnmatched students from grades.json:\n")
                    unique_unmatched = list(set(unmatched_students))  # 去重
                    for name in unique_unmatched:
                        self.output_text.insert(tk.END, f"- {name}\n")
        except FileNotFoundError:
            self.output_text.insert(tk.END, "grades.json file not found.\n")
        except json.JSONDecodeError:
            self.output_text.insert(tk.END, "Error decoding JSON from grades.json file.\n")
        except KeyError as e:
            self.output_text.insert(tk.END, f"Key error: {e} in grades.json file.\n")

    def display_class(self):
        """显示当前班级的学生信息"""
        self.output_text.delete(1.0, tk.END)  # 清空输出区域
        self.output_text.insert(tk.END, "Current class:\n")
        for student in self.class_obj.students.to_list():
            self.output_text.insert(
                tk.END,
                f"{student.name}: {student.scores} (Total Score: {student.total_score})\n"
            )

    def sort_students_by_name(self):
        """按姓名排序学生并显示结果"""
        self.class_obj.sort_students_by_name()
        self.display_class()

    def sort_students_by_total_score(self):
        """按总分排序学生并显示结果"""
        self.class_obj.sort_students_by_total_score()
        self.display_class()

    def sort_students_by_course_score(self):
        """按特定课程的成绩排序学生并显示结果"""
        course_name = simpledialog.askstring("Input", "Enter course name:")
        if course_name and course_name in [course for student in self.class_obj.students.to_list() for course in student.scores]:
            self.class_obj.sort_students_by_course_score(course_name)
            self.display_class()
        else:
            messagebox.showerror("Error", "Invalid or missing course name.")


if __name__ == "__main__":
    root = tk.Tk()
    app = CourseManagement(root)
    root.mainloop()